#include "gprs_command.h"
#include "string.h"
#include "platformAPI.h"
#include "stream_parse.h"

#define DEBUG_GRRS_COMMAND 1


#define MUXCON_ON   (1)
#define MUXCON_OFF  (0)

static uint8_t send_action = 0;

static int8_t cmdSend(uint8_t *buf, uint32_t len)
{
    int32_t ret = -1;
    if(send_action == 0)
    {
	ret = gprsUartWrite(buf,len);
    }

    return ret;
}

#define CHECK_OK      0
#define CHECK_NOK    -1
#define TO_BE_CHECK  -2


static int8_t res_parse = TO_BE_CHECK;
static uint8_t stage_parse = 0;
static uint8_t state_parse = 0;
static uint8_t state_parseOK = 0;
static uint8_t state_parseERROR = 0;

static void parseAT(uint8_t data)
{
    uint8_t buf[] = "AT\r";
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
}

static void parseSetMux(uint8_t data)
{
    uint8_t buf[] = "AT+CIPMUX=1\r";
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
}

static volatile uint8_t parsed_data;

static void parseCheckMux(uint8_t data)
{
    uint8_t buf[] = "AT+CIPMUX?\r";
    uint8_t key[] = "+CIPMUX:";
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    //printf("[%s] stage_parse [%d] data [%c]\n",__FUNCTION__,stage_parse,data);
    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		//printf("[%s] cmd found\n",__FUNCTION__);
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else if(stage_parse == 1)
    {
	if(key[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(key))
	    {
		//printf("[%s] key found\n",__FUNCTION__);
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else if(stage_parse == 2)
    {
	parsed_data = data;
	//printf("[%s] parsed_data [%d]\n",__FUNCTION__,parsed_data);
	stage_parse++;
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		//printf("[%s] ok\n",__FUNCTION__);
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		//printf("[%s] error\n",__FUNCTION__);
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
    
}

static uint8_t tcpCmd[50] = "AT+CIPSTART=\"TCP\",";

static void parseStartTCP(uint8_t data)
{
    uint8_t *buf = tcpCmd;
    uint8_t key[] = "+CIPNUM:";
    uint8_t ok[] = "CONNECT OK";
    uint8_t error[] = "ERROR";

    //printf("[%s] test\n",__FUNCTION__);

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    //print("[%s] stage_parse [%d]\n",__FUNCTION__,stage_parse);

    if(stage_parse == 0)
    {
	if(tcpCmd[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(tcpCmd))
	    {
		printf("[%s] cmd found\n",__FUNCTION__);
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else if(stage_parse == 1)
    {
	if(key[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(key))
	    {
		printf("[%s] key found\n",__FUNCTION__);
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}

	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		printf("[%s] error found\n",__FUNCTION__);
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
    else if(stage_parse == 2)
    {
	parsed_data = data;
	printf("[%s] channel [%d]\n",__FUNCTION__,parsed_data);
	stage_parse++;
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		printf("[%s] ok found\n",__FUNCTION__);
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}
    }
}


static void parseCheckSIM(uint8_t data)
{
    uint8_t buf[] = "AT+CCID\r";
    uint8_t ok[] = "+SCID: SIM Card ID:";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
}

static void parseSetMT(uint8_t data)
{
    uint8_t buf[] = "AT+CGATT=1\r";
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
}

static void parseDefinePDP(uint8_t data)
{
    uint8_t buf[] = "AT+CGDCONT=1,\"IP\",\"cmnet\"\r";
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
}


static void parseActivatePDP(uint8_t data)
{
    uint8_t buf[] = "AT+CGACT=1,1\r";
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }

}

static uint8_t conStatus[4] = {MUXCON_OFF, MUXCON_OFF, MUXCON_OFF, MUXCON_OFF};
static uint8_t checkCount[4] = {0};
static uint8_t checkover[4] = {0};
static uint8_t checkflag[4] = {0};

static void checkCon(uint8_t num,uint8_t data)
{
    uint8_t con[] = "CONNECT OK";
    uint8_t over[] = "\r\n";


    //printf("[%s] num [%d] , data [%c]\n",__FUNCTION__,num,data);
    if((num + '0') == data)
    {
	//printf("[%s] channel [%c]\n",__FUNCTION__,num+'0');
	checkflag[num]++;
    }

    if(checkflag[num] > 0)
    {
	//printf("[%s] channel [%c]\n",__FUNCTION__,num+'0');
	if(con[checkCount[num]] == data)
	{
	    checkCount[num]++;
	    if(checkCount[num] == strlen(con))
	    {
		checkCount[num] = 0;
		//printf("[%s] con OK\n",__FUNCTION__);
		checkover[num] = 0;
		conStatus[num] = MUXCON_ON;
	    }
	}
	else
	{
	    checkCount[num] = 0;
	    conStatus[num] = MUXCON_OFF;
	}

	if(over[checkflag[num] - 1] == data)
	{
	    checkflag[num]++;
	    if(checkflag[num] >= (strlen(over) + 1))
	    {
		//printf("[%s] done\n",__FUNCTION__);
		checkover[num] = 0;
		checkflag[num] = 0;
	    }
	}

	checkover[num]++;
	if(checkover[num] > 15)
	{
	    //printf("[%s] overcount\n",__FUNCTION__);
	    checkflag[num] = 0;
	    checkover[num] = 0;
	}
    }
}

static void parseCheckCon(uint8_t data)
{
    uint8_t buf[] = "AT+CIPSTATUS\r";
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		//printf("[%s] found cmd\n",__FUNCTION__);
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else 
    {
	checkCon(0,data);
	checkCon(1,data);
	checkCon(2,data);
	checkCon(3,data);

	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}

	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		//printf("[%s] ok found\n",__FUNCTION__);
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}
    }
}

static uint8_t parse_close_count = 0;
static uint8_t parse_close_stage = 0;

static void parseClosedMessage(uint8_t data)
{
    uint8_t buf[] = "+TCPCLOSED:";

    if(parse_close_stage == 0)
    {
	if(buf[parse_close_count] == data)
	{
	    parse_close_count++;
	    if(parse_close_count == strlen(buf))
	    {
		printf("[%s] find tcp closed\n",__FUNCTION__);
		parse_close_count = 0;
		parse_close_stage++;
	    }
	}
	else
	{
	    parse_close_count = 0;
	}
    }
    else if(parse_close_stage == 1)
    {
	printf("[%s] channel [%d] closed\n",__FUNCTION__,data - '0');
	conStatus[data - '0'] = MUXCON_OFF;
	parse_close_stage = 0;
    }
}

static uint8_t tcp_send[20] = "AT+CIPSEND=0,";

static void parseSendMux(uint8_t data)
{
    uint8_t *buf = tcp_send;
    uint8_t ok[] = ">";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }

}

struct tcp_pack
{
    uint8_t buf[1024];
    uint32_t len;
    uint8_t channel;
};

static struct tcp_pack tcp_data;
static uint8_t pack_ready = 0;
static uint8_t pack_tmp[1024] = {0};
static uint8_t pack_state = 0;
static uint8_t pack_count = 0;
static uint8_t pack_channel = 0;
static uint8_t pack_str[5] = {0};
static uint32_t pack_len = 0;


static uint32_t strToUint32(uint8_t *str)
{
    uint8_t count = 0;
    uint32_t data = 0;
    while( *(str + count) != 0)
    {
	data = (data * 10) + (*(str + count) - '0');
	count++;
    }
    return data;
}

static void parseReadMux(data)
{
    uint8_t buf[] = "+CIPRCV:";
    //uint8_t close[] = "+TCPCLOSED:"
    static uint8_t count = 0;
    uint32_t i;

    if(pack_state == 0)
    {
	/* find buf*/
	if(buf[pack_count] == data)
	{
	    pack_count++;
	    if(pack_count == 8)
	    {
		//printf("[%s] find +CIPRCV:\n",__FUNCTION__);
		pack_count = 0;
		pack_state = 1;
	    }
	}
	else
	{
	    pack_count = 0;
	}
    }
    else if(pack_state == 1)
    {
	if(data != ',')
	{
	    pack_channel = data;
	    //printf("[%s] pack_channel [%d]\n",__FUNCTION__,pack_channel);
	}
	else
	{
	    pack_state = 2;
	}
    }
    else if(pack_state == 2)
    {
	if(data != ',')
	{
	    pack_str[count++] = data;
	    //printf("[%s] pack_str [%s]\n",__FUNCTION__,pack_str);
	}
	else
	{
	    count = 0;
	    pack_len = strToUint32(pack_str);
	    //printf("[%s] pack_len [%d]\n",__FUNCTION__,pack_len);
	    pack_count = 0;
	    pack_state = 3;
	}
    }
    else if(pack_state == 3)
    {
	if(pack_count < pack_len)
	{
	    pack_tmp[pack_count++] = data;
	}
	else if(pack_ready == 0)
	{
	    //printf("[%s] pack_count [%d]\n",__FUNCTION__,pack_count);
	    //printf("[%s] pack_len [%d]\n",__FUNCTION__,pack_len);
	    printf("[%s] find one packet of tcp\n",__FUNCTION__);
	    memset(tcp_data.buf,0,1024);
	    for(count = 0; count < pack_len; count++)
	    {
		tcp_data.buf[count] = pack_tmp[count];
	    }
	    tcp_data.len = pack_len;
	    tcp_data.channel = pack_channel;
	    memset(pack_tmp,0,1024);
	    memset(pack_str,0,5);
	    pack_state = 0;
	    pack_count = 0;
	    pack_channel = 0;
	    pack_len = 0;
	    pack_ready = 1;
	    count = 0;
	}
    }
}

static uint8_t parseClose[15] = "AT+CIPCLOSE=\r";

static void parseCloseCon(uint8_t data)
{
    uint8_t *buf = parseClose;
    uint8_t ok[] = "OK";
    uint8_t error[] = "ERROR";

    if(res_parse != TO_BE_CHECK)
    {
	return;
    }

    if(stage_parse == 0)
    {
	if(buf[state_parse] == data)
	{
	    state_parse++;
	    if(state_parse == strlen(buf))
	    {
		state_parse = 0;
		stage_parse++;
	    }
	}
	else
	{
	    state_parse = 0;
	}
    }
    else
    {
	if(ok[state_parseOK] == data)
	{
	    state_parseOK++;
	    if(state_parseOK == strlen(ok))
	    {
		state_parseOK = 0;
		stage_parse = 0;
		res_parse = CHECK_OK;
	    }
	}
	else
	{
	    state_parseOK = 0;
	}


	if(error[state_parseERROR] == data)
	{
	    state_parseERROR++;
	    if(state_parseERROR == strlen(error))
	    {
		state_parseERROR = 0;
		stage_parse = 0;
		res_parse = CHECK_NOK;
	    }
	}
	else
	{
	    state_parseERROR = 0;
	}
    }
}

#define ACTION_IDLE         0
#define ACTION_CHECK_AT     1
#define ACTION_SET_MUX      2
#define ACTION_CHECK_MUX    3
#define ACTION_START_TCP    4
#define ACTION_CHECK_SIM    5
#define ACTION_SET_MT       6
#define ACTION_DEF_PDP      7
#define ACTION_EN_PDP       8
#define ACTION_CHECK_CON    9
#define ACTION_SEND_MUX    10
#define ACTION_CLOSE_CON   11

static volatile action_number = ACTION_IDLE;

int8_t gprsRuntime(void)
{
    uint8 tmp;
    int32_t ret;

    while(1)
    {
	ret = gprsUartRead(&tmp,1);
	if(ret == 1)
	{
	    switch(action_number)
	    {
	    case ACTION_IDLE:
		break;
	    case ACTION_CHECK_AT:
		parseAT(tmp);
		break;
	    case ACTION_SET_MUX:
		parseSetMux(tmp);
		break;
	    case ACTION_CHECK_MUX:
		parseCheckMux(tmp);
		break;
	    case ACTION_START_TCP:
		//printf("[%s] start tcp\n",__FUNCTION__);
		parseStartTCP(tmp);
		break;
	    case ACTION_CHECK_SIM:
		parseCheckSIM(tmp);
		break;
	    case ACTION_SET_MT:
		parseSetMT(tmp);
		break;
	    case ACTION_DEF_PDP:
		parseDefinePDP(tmp);
		break;
	    case ACTION_EN_PDP:
		parseActivatePDP(tmp);
		break;
	    case ACTION_CHECK_CON:
		parseCheckCon(tmp);
		break;
	    case ACTION_SEND_MUX:
		parseSendMux(tmp);
		break;
	    case ACTION_CLOSE_CON:
		parseCloseCon(tmp);
		break;
	    default:
		break;
	    }
	    parseReadMux(tmp);
	    parseClosedMessage(tmp);
	}
	else
	{
	    break;
	}
    }
}

int8_t gprsActiveCheck(void)
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_CHECK_AT;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;



    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}

int8_t gprsSetMuxCon(void)
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT+CIPMUX=1\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_SET_MUX;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}

int8_t gprsCheckMuxCon()
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT+CIPMUX?\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_CHECK_MUX;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    if(res_parse == CHECK_OK)
    {
	ret = parsed_data - '0';
    }
    else
    {
	ret = GPRS_NOK;
    }

    printf("[%s] mux [%d]\n",__FUNCTION__,ret);
    action_number = ACTION_IDLE;
    return ret;
}

int8_t gprsStartTCP(uint8_t *ip,uint32_t port_num)
{
    uint8_t buf[50] = "AT+CIPSTART=\"TCP\",";
    uint8_t port[6] = {0};
    int8_t ret = 0;
    int8_t con_channel = '0';
    uint32_t overtime = 100;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }
    
    strcat(buf,ip);
    strcat(buf,",");
    sprintf(port,"%d",port_num);
    strcat(buf,port);
    strcat(buf,"\r");

    memcpy(tcpCmd,buf,50);

    action_number = ACTION_START_TCP;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    //printf("[%s] cmd [%s]\n",__FUNCTION__,buf);

    gprsUartWrite(buf,strlen(buf));
    //printf("[%s] test\n",__FUNCTION__);
    while(1)
    {
	//printf("[%s] test1\n",__FUNCTION__);
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    printf("[%s] res_parse [%d]\n",__FUNCTION__,res_parse);

    if(res_parse == CHECK_OK)
    {
	con_channel = parsed_data;
	ret = con_channel;
    }
    else
    {
	ret = GPRS_NOK;
    }

    action_number = ACTION_IDLE;
    return ret;
}

int8_t gprsCheckSIM(void)
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT+CCID\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_CHECK_SIM;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;



    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}

int8_t gprsSetMT(void)
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT+CGATT=1\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_SET_MT;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;



    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}


int8_t gprsDefinePDP(void)
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT+CGDCONT=1,\"IP\",\"cmnet\"\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_DEF_PDP;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}

int8_t gprsActivatePDP(void)
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT+CGACT=1,1\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_EN_PDP;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}


int8_t gprsReset(void)
{
    uint32_t count = 0;
    int8_t ret = 0;
    /*step0. set GPIO*/
    PIN_FUNC_SELECT(GPIO_PIN_REG(15),FUNC_GPIO15); /* this is for A6.RST*/
    PIN_FUNC_SELECT(GPIO_PIN_REG(5),FUNC_GPIO5); /* this is for A6.PWR_KEY*/

    PIN_PULLUP_EN(GPIO_PIN_REG(15));
    PIN_PULLUP_EN(GPIO_PIN_REG(5));

    /*step1. A6.RST -> 0(esp8266.GPIO15 -> 1) , A6.PWR_KEY -> 0*/
    GPIO_OUTPUT_SET(GPIO_ID_PIN(15),1);
    GPIO_OUTPUT_SET(GPIO_ID_PIN(5),0);
    systemDelayMs(500);
    
    /*step2. A6.RST -> 1(esp8266.GPIO15 -> 0) , AT.PWR_KEY -> 1 , hold > 2S */
    GPIO_OUTPUT_SET(GPIO_ID_PIN(15),0);
    GPIO_OUTPUT_SET(GPIO_ID_PIN(5),1);
    systemDelayMs(5000);

    while(1)
    {
	printf("[%s] check AT\n",__FUNCTION__);
	ret = gprsActiveCheck();
	if(ret == 0)
	{
	    break;
	}
	systemDelayMs(100);
	count++;
	if(count == 5)
	{
	    return -1;
	}
    }
#if 1
    count = 0;
    while(1)
    {
	printf("[%s] check SIM\n",__FUNCTION__);
	ret = gprsCheckSIM();
	if(ret == 0)
	{
	    break;
	}
	systemDelayMs(100);
	count++;
	if(count == 5)
	{
	    return -1;
	}
    }

    count = 0;
    while(1)
    {
	printf("[%s] set MT\n",__FUNCTION__);
	ret = gprsSetMT();
	if(ret == 0)
	{
	    break;
	}
	systemDelayMs(100);
	count++;
	if(count == 5)
	{
	    return -1;
	}
    }

    count = 0;
    while(1)
    {
	ret = gprsDefinePDP();
	if(ret == 0)
	{
	    break;
	}
	systemDelayMs(100);
	count++;
	if(count == 5)
	{
	    return -1;
	}
    }

    count = 0;
    while(1)
    {
	printf("[%s] activate PDP\n",__FUNCTION__);
	ret = gprsActivatePDP();
	if(ret == 0)
	{
	    break;
	}
	systemDelayMs(100);
	count++;
	if(count == 5)
	{
	    return -1;
	}
    }
#endif
    return 0;
}

int8_t gprsCheckCon(void)
{
    uint32_t overtime = 50;
    uint8_t buf[] = "AT+CIPSTATUS\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    action_number = ACTION_CHECK_CON;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    printf("[%s] check over\n",__FUNCTION__);
	    printf("[%s] conStatus [%d] [%d] [%d] [%d]\n",__FUNCTION__
		   ,conStatus[0],conStatus[1],conStatus[2],conStatus[3]);
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}

int32_t gprsTCPsend(int8_t channel,uint8_t *buf, uint32_t len)
{
    return -1;
}

int32_t gprsTCPsendMux(int8_t channel,uint8_t *buf, uint32_t len)
{
    uint32_t overtime = 50;
    uint8_t cmd[20] = "AT+CIPSEND=0,";
    int8_t ret;
    

    if(action_number != ACTION_IDLE)
    {
	printf("[%s] action busy\n",__FUNCTION__);
	return GPRS_BUSY;
    }

    if(conStatus[channel - '0'] != MUXCON_ON)
    {
	printf("[%s] con [%d], status [%d], not ok\n",__FUNCTION__,channel,conStatus[channel - '0']);
	return GPRS_CON_LOST;
    }

    cmd[11] = channel;
    cmd[12] = ',';
    sprintf(&cmd[13],"%d\r",len);

    action_number = ACTION_SEND_MUX;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    gprsUartWrite(cmd,strlen(cmd));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    if(res_parse != CHECK_OK)
    {
	action_number = ACTION_IDLE;
	return GPRS_NOK;
    }

    gprsUartWrite(buf,len);
    action_number = ACTION_IDLE;

    return len;
}

int32_t gprsTCPreadMux(int8_t channel,uint8_t *buf,uint32_t len)
{
    uint32_t count = 0;
    //printf("[%s] pack_ready [%d], channel [%c]\n",__FUNCTION__,pack_ready,tcp_data.channel);
    if(pack_ready == 1 &&
       tcp_data.channel == channel)
    {
	len = (tcp_data.len > len)?len:tcp_data.len;
	for(count = 0; count < len; count++)
	{
	    buf[count] = tcp_data.buf[count];
	}
	pack_ready = 0;
	return len;
    }
    else if(conStatus[channel - '0'] != MUXCON_ON)
    {
	printf("[%s] channel [%d], con [%d]\n",__FUNCTION__,channel - '0',conStatus[channel - '0']);
	return GPRS_CON_LOST;
    }
    else
    {
	//printf("[%s] channel [%d], con [%d]\n",__FUNCTION__,channel - '0',conStatus[channel - '0']);
	return GPRS_NOK;
    }
}

int8_t gprsCloseCon(int8_t channel)
{
    uint32_t overtime = 50;
    uint8_t buf[15] = "AT+CIPCLOSE=\r";
    int8_t ret;

    if(action_number != ACTION_IDLE)
    {
	return GPRS_BUSY;
    }

    if(conStatus[channel - '0'] != MUXCON_ON)
    {
	return GPRS_OK;
    }

    if(gprsCheckMuxCon() == MUXCON_ON)
    {
	buf[12] = channel;
	buf[13] = '\r';
    }
    else
    {
	buf[11] = '\r';
    }

    memcpy(parseClose,buf,15);

    action_number = ACTION_CLOSE_CON;
    res_parse = TO_BE_CHECK;
    state_parse = 0;
    stage_parse = 0;
    state_parseOK = 0;
    state_parseERROR = 0;

    gprsUartWrite(buf,strlen(buf));

    while(1)
    {
	if(res_parse != TO_BE_CHECK)
	{
	    break;
	}
	systemDelayMs(100);
	overtime--;
	if(overtime == 0)
	{
	    break;
	}
    }

    ret = res_parse;
    action_number = ACTION_IDLE;
    return ret;
}

